Object.defineProperty()

学习记录

语法

Object.defineProperty(obj, prop, descriptor)

参数

obj
需要被操作的目标对象
prop
目标对象需要定义或修改的属性的名称。
descriptor
将被定义或修改的属性的描述符。

其中descriptor包括数据描述符和存取描述符

数据描述符和存取描述符均具有以下可选键值:

configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
enumerable
当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
数据描述符同时具有以下可选键值:

value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:

get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
以上摘自MDN

实践

创建属性

如果对象中不存在指定的属性,Object.defineProperty()就创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。拥有布尔值的字段的默认值都是false。value,get和set字段的默认值为undefined。定义属性时如果没有get/set/value/writable,那它被归类为数据描述符。

1
2
3
4
5
6
7
8
9
10
11
12
13
const log = console.log.bind(console)
function foo(){}
Object.defineProperty(foo.prototype,'z',{get:function(){return 1}})
var obj = new foo()
log(obj.z) //1 obj 无z属性 根据原型链查找foo.prototype的z属性,因为有get方法所以return 1
obj.z = 10 修改obj.z
log(obj.z) //1
因为obj.z虽然无z属性,根据原型链查找的时候 发现有对应的z的get方法或者set方法
尝试赋值的时候是会通过get和set方法来走的。不会变成给当前obj添加一个z属性。
Object.defineProperty(obj,'z',{value:100,configurable:true,writable:true})
log(obj.z) //100 通过Object.defineProperty方式来给obj添加z属性
obj.z = 200
log(obj.z) //200 200是因为writable:true 可以修改属性值

查找属性标签

1
2
3
4
Object.getOwnPropertyDescriptor({a:true},'a')
// {value: true, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor({b:true},'a') //undefined 对象里无a属性

顺便上一张图


摘自imooc